#include "xmlParse.h"


qXmlParse::qXmlParse()
{
	doc_ = nullptr;
}

qXmlParse::~qXmlParse()
{
	if (doc_)
		xmlFreeDoc(doc_);
}

char* qXmlParse::convChar(char* in, const char* fromEncode, const char* toEncode)
{
	if (!in)
		return nullptr;

	size_t size = strlen(in);
	size_t outsize = 2 * size + 1;
	char* out = new char[outsize];
	if (out)
	{
		bzero(out, outsize);
		if (fromEncode && toEncode)
		{
			iconv_t ret = iconv_open(toEncode, fromEncode);
			if ((iconv_t)-1 == ret)
			{
				delete[]out;
				out = nullptr;
			}
			else
			{
				char* fromtmp = in;
				char* totmp = out;
				size_t tmpoutsize = outsize - 1;
				size_t convsize = iconv(ret, &fromtmp, &size, &totmp, &tmpoutsize);
				if (convsize == -1)
				{
					delete[] out;
					out = nullptr;
				}
				iconv_close(ret);
			}
		}
		else
		{
			strncpy(out, in, size);
		}

	}
	return out;
}

bool qXmlParse::initFile(const std::string& filename)
{
	if (filename.empty())
	{
		LOG_ERROR("filename is null FFL[%s,%s,%d]", LOG_FFL);
		return false;
	}

	if (doc_)
	{
		xmlFreeDoc(doc_);
		doc_ = nullptr;
	}

	doc_ = xmlParseFile(filename.c_str());
	return doc_ != nullptr;
}

xmlNodePtr qXmlParse::getRootNode()
{
	return xmlDocGetRootElement(doc_);
}

xmlNodePtr qXmlParse::getChildNode(xmlNodePtr node, const char* nodename)
{
	xmlNodePtr childNode = node->children;;

	if (nodename)
	{
		while (childNode)
		{
			if (!xmlStrcmp(childNode->name, (const xmlChar*)nodename))
			{
				break;
			}
			childNode = childNode->next;
		}
	}
	else
	{
		while (childNode)
		{
			if (!xmlNodeIsText(childNode))
			{
				break;
			}
			childNode = childNode->next;
		}
	}

	return childNode;
}

xmlNodePtr qXmlParse::getNextNode(xmlNodePtr node, const char* nodename)
{
	if (!node)
		return nullptr;

	xmlNodePtr nextNode = node->next;
	if (nodename)
	{
		while (nextNode)
		{
			if (!xmlStrcmp(nextNode->name, (const xmlChar*)nodename))
				break;
			nextNode = nextNode->next;
		}
	}
	else
	{
		while (nextNode)
		{
			if (!xmlNodeIsText(nextNode))
				break;
			nextNode = node->next;
		}
	}
	return nextNode;

}

bool qXmlParse::getNodePropNum(xmlNodePtr node, const char* propname, void* dstname, size_t dstsize)
{
	if (!node || !propname || !dstname || !dstsize)
		return false;

	char* prop = (char*)xmlGetProp(node, (const xmlChar*)propname);
	if (!prop)
		return false;

	switch (dstsize)
	{
	case sizeof(uint8) :
		*(uint8*)dstname = (uint8)atoi(prop);
	case sizeof(uint16) :
		*(uint16*)dstname = (uint16)atoi(prop);
	case sizeof(uint32) :
		*(uint32*)dstname = atoi(prop);
	case sizeof(uint64) :
		*(uint64*)dstname = atoll(prop);
	default:
		return false;
	}
	xmlFree(prop);
	return true;

}

bool qXmlParse::getNodePropStr(xmlNodePtr node, const char* propname, std::string& str)
{
	if (!node || !propname)
		return false;

	char* prop = (char*)xmlGetProp(node, (const xmlChar*)propname);
	if (!prop)
		return false;

	char* out = convChar(prop, "UTF-8", (char*)doc_->encoding);
	if (out)
	{
		str.clear();
		str = out;
		delete[] out;
	}

	xmlFree(prop);
	return true;
}
